home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-19 | 13.4 KB | 424 lines | [TEXT/CWIE] |
-
- #include "ListTemplate.h"
-
- //
- // For BlockMoveData
- //
- #include <Memory.h>
-
- //================================================================================
- // CLASS TAbstractListIteratorIterator
- //
- // As it says, this is an iterator class that enumerates a list of iterators.
- //================================================================================
-
- class TAbstractListIteratorIterator
- {
- public:
- TAbstractListIteratorIterator(TAbstractListIterator** iterList, UInt16* listSize) :
- fIterList(iterList),
- fListSize(listSize),
- fCurrent(0),
- fRemovedCurrent(false) {}
-
- Boolean More() const { return fCurrent < *fListSize; }
- TAbstractListIterator* Current() const { return fIterList[fCurrent]; }
- void Next() { if(fRemovedCurrent == false) ++fCurrent; fRemovedCurrent = false; }
- void RemoveCurrent();
-
- private:
- TAbstractListIterator** fIterList;
- UInt16* fListSize;
- UInt16 fCurrent;
- Boolean fRemovedCurrent;
- };
-
- //-------------------------------------------------------------------
- // TAbstractListIteratorIterator::RemoveCurrent
- //-------------------------------------------------------------------
- void TAbstractListIteratorIterator::RemoveCurrent()
- {
- SInt32 remainingItems = (*fListSize - fCurrent) - 1;
-
- if(remainingItems > 0)
- {
- BlockMove((Ptr)&fIterList[fCurrent + 1], (Ptr)&fIterList[fCurrent], sizeof(Ptr) * remainingItems);
- }
- --(*fListSize);
- fRemovedCurrent = true;
- }
-
- //================================================================================
- // CLASS TListStorage
- //================================================================================
-
- //-------------------------------------------------------------------
- // TListStorage::TListStorage
- //-------------------------------------------------------------------
- TListStorage::TListStorage(const TListStorage& copyFrom) :
- fListData(nil),
- fItemSize(copyFrom.fItemSize),
- fItemsInList(copyFrom.ItemsInList()),
- fSpaceReserved(0),
- #if DEBUGPREEMPTIVELOCK
- fReadLocks(0),
- fWriteLocks(0),
- #endif
- fIteratorList(nil),
- fNumberOfIterators(0),
- fIteratorListReservedSpace(0)
- {
- copyFrom.LockForReading();
-
- this->InsureAdequateSpace(copyFrom.ItemsInList());
- if(copyFrom.ItemsInList())
- BlockMoveData(copyFrom.ItemAddress(0), this->ItemAddress(0), this->ItemsInList() * fItemSize);
-
- copyFrom.RelinquishReadLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::~TListStorage
- //-------------------------------------------------------------------
- TListStorage::~TListStorage()
- {
- this->NotifyListDestroyed();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::Clone
- //-------------------------------------------------------------------
- TListStorage* TListStorage::Clone() const
- {
- TListStorage* clonedList = new TListStorage(*this);
-
- return clonedList;
- }
-
- //-------------------------------------------------------------------
- // TListStorage::Add
- //-------------------------------------------------------------------
- void TListStorage::Add(const char* elementAddress)
- {
- //
- // Don't lock for writing, InsertAtEnd does that.
- //
- this->InsertAtEnd(elementAddress);
- }
-
- //-------------------------------------------------------------------
- // TListStorage::Remove
- //-------------------------------------------------------------------
- Boolean TListStorage::Remove(const char* elementToRemove, ListElementCompareProcPtr compareProc)
- {
- this->LockForWriting();
- SInt32 itemIndex = this->IndexOfItem(elementToRemove, compareProc);
-
- if(itemIndex >= 0)
- this->RemoveItemAtIndex(itemIndex);
-
- this->RelinquishWriteLock();
-
- return (itemIndex >= 0);
- }
-
- //-------------------------------------------------------------------
- // TListStorage::InsertAtBeginning
- //-------------------------------------------------------------------
- void TListStorage::InsertAtBeginning(const char* elementAddress)
- {
- this->LockForWriting();
- InsureAdequateSpace(this->ItemsInList() + 1);
- if(this->ItemsInList() > 0)
- BlockMoveData(this->ItemAddress(0), this->ItemAddress(1), this->ItemsInList() * fItemSize);
- ++fItemsInList;
- this->ReplaceItemAtIndex(0, elementAddress);
- this->RelinquishWriteLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::InsertAtEnd
- //-------------------------------------------------------------------
- void TListStorage::InsertAtEnd(const char* elementAddress)
- {
- this->LockForWriting();
- InsureAdequateSpace(this->ItemsInList() + 1);
- ++fItemsInList;
- this->ReplaceItemAtIndex(fItemsInList-1, elementAddress);
- this->RelinquishWriteLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::RemoveFromBeginning
- //-------------------------------------------------------------------
- void TListStorage::RemoveFromBeginning()
- {
- this->LockForWriting();
- this->RemoveItemAtIndex(0);
- this->RelinquishWriteLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::RemoveFromEnd
- //-------------------------------------------------------------------
- void TListStorage::RemoveFromEnd()
- {
- this->LockForWriting();
- this->RemoveItemAtIndex(fItemsInList - 1);
- this->RelinquishWriteLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::FirstItem
- //-------------------------------------------------------------------
- void TListStorage::FirstItem(char* copyToBuffer) const
- {
- this->LockForReading();
- this->ItemAtIndex(0, copyToBuffer);
- this->RelinquishReadLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::LastItem
- //-------------------------------------------------------------------
- void TListStorage::LastItem(char* copyToBuffer) const
- {
- this->LockForReading();
- this->ItemAtIndex(this->ItemsInList() - 1,copyToBuffer);
- this->RelinquishReadLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::ReverseOrderOfList
- //-------------------------------------------------------------------
- void TListStorage::ReverseOrderOfList(char* tempBuffer)
- {
- this->LockForWriting();
- SInt32 midPoint = this->ItemsInList() / 2;
- for(SInt32 i=0; i<midPoint; ++i)
- {
- this->ItemAtIndex(i, tempBuffer);
- this->ReplaceItemAtIndex(i, this->ItemAddress(fItemsInList - 1 - i));
- this->ReplaceItemAtIndex(fItemsInList - 1 - i, tempBuffer);
- }
- this->RelinquishWriteLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::MakeEmpty
- //-------------------------------------------------------------------
- void TListStorage::MakeEmpty()
- {
- this->LockForWriting();
- fItemsInList = 0;
- this->RelinquishWriteLock();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::LockForReading
- //-------------------------------------------------------------------
- void TListStorage::LockForReading() const
- {
- #if DEBUGPREEMPTIVELOCK
- if(fWriteLocks > 0)
- DebugStr("\pCalled LockForReading while write lock was on");
-
- ++((TListStorage*)this)->fReadLocks;
- #endif
- }
-
- //-------------------------------------------------------------------
- // TListStorage::RelinquishReadLock
- //-------------------------------------------------------------------
- void TListStorage::RelinquishReadLock() const
- {
- #if DEBUGPREEMPTIVELOCK
- if(fReadLocks < 1)
- DebugStr("\pToo many calls to RelinquishReadLock");
-
- --((TListStorage*)this)->fReadLocks;
- #endif
- }
-
- //-------------------------------------------------------------------
- // TListStorage::LockForWriting
- //-------------------------------------------------------------------
- void TListStorage::LockForWriting()
- {
- #if DEBUGPREEMPTIVELOCK
- if(fReadLocks > 0)
- DebugStr("\pCalled LockForWriting while read lock was on");
-
- ++fWriteLocks;
- #endif
- }
-
- //-------------------------------------------------------------------
- // TListStorage::RelinquishWriteLock
- //-------------------------------------------------------------------
- void TListStorage::RelinquishWriteLock()
- {
- #if DEBUGPREEMPTIVELOCK
- if(fWriteLocks < 1)
- DebugStr("\pToo many calls to RelinquishWriteLock");
-
- --fWriteLocks;
- #endif
- }
-
- //-------------------------------------------------------------------
- // TListStorage::ItemAtIndex
- //
- // Not preemptive-safe, must call LockForReading before using
- //-------------------------------------------------------------------
- void TListStorage::ItemAtIndex(SInt32 itemIndex, char* copyToBuffer) const
- {
- if((itemIndex >= 0 ) && (itemIndex < this->ItemsInList()))
- BlockMoveData(this->ItemAddress(itemIndex), copyToBuffer, fItemSize);
- else
- DebugStr("\pItem index out of range for get");
- }
-
- //-------------------------------------------------------------------
- // TListStorage::ReplaceItemAtIndex
- //
- // Not preemptive-safe, must call LockForWriting before using
- //-------------------------------------------------------------------
- void TListStorage::ReplaceItemAtIndex(SInt32 itemIndex, const char* dataToReplaceWith)
- {
- if((itemIndex >= 0 ) && (itemIndex < this->ItemsInList()))
- BlockMoveData(dataToReplaceWith, this->ItemAddress(itemIndex), fItemSize);
- else
- DebugStr("\pItem index out of range for replace");
- }
-
- //-------------------------------------------------------------------
- // TListStorage::IndexOfItem
- //
- // Not preemptive-safe, must call LockForReading before using, and
- // must not RelinquishReadLock until after index value obtained
- // from this routine is no longer needed.
- //-------------------------------------------------------------------
- SInt32 TListStorage::IndexOfItem(const char* elementToFind, ListElementCompareProcPtr compareProc, SInt32 indexToStartAt /*= 0*/) const
- {
- SInt32 theItemIndex = -1;
-
- for(SInt32 i=indexToStartAt; i<this->ItemsInList(); ++i)
- {
- if((*compareProc)(elementToFind, this->ItemAddress(i)))
- {
- theItemIndex = i;
- break;
- }
- }
-
- return theItemIndex;
- }
-
- //-------------------------------------------------------------------
- // TListStorage::RemoveItemAtIndex
- //
- // Not preemptive-safe, must call LockForWriting before using
- //-------------------------------------------------------------------
- void TListStorage::RemoveItemAtIndex(SInt32 item)
- {
- if((item >= 0) && (item < this->ItemsInList()))
- {
- if(item + 1 < this->ItemsInList())
- BlockMoveData(this->ItemAddress(item + 1), this->ItemAddress(item), fItemSize * (fItemsInList - (item + 1)));
-
- --fItemsInList;
- }
- }
-
- //-------------------------------------------------------------------
- // TListStorage::InsureAdequateSpace
- //
- // Not preemptive-safe, must call LockForWriting before using
- //-------------------------------------------------------------------
- void TListStorage::InsureAdequateSpace(SInt32 numberOfItems)
- {
- if(numberOfItems > fSpaceReserved)
- {
- SInt32 newReservedSpace = fSpaceReserved + kAllocationChunk;
- char* newData = new char[newReservedSpace * fItemSize];
-
- if(fSpaceReserved > 0)
- {
- BlockMoveData(fListData, newData, fSpaceReserved * fItemSize);
- delete fListData;
- }
-
- fListData = newData;
- fSpaceReserved = newReservedSpace;
- }
- }
-
- //-------------------------------------------------------------------
- // TListStorage::AddIterator
- //-------------------------------------------------------------------
- void TListStorage::AddIterator(TAbstractListIterator* newIter)
- {
- this->InsureSpaceForIteratorList(fNumberOfIterators + 1);
-
- fIteratorList[fNumberOfIterators] = newIter;
- ++fNumberOfIterators;
- }
-
- //-------------------------------------------------------------------
- // TListStorage::RemoveIterator
- //-------------------------------------------------------------------
- void TListStorage::RemoveIterator(TAbstractListIterator* iterToRemove)
- {
- for(TAbstractListIteratorIterator iter(fIteratorList, &fNumberOfIterators); iter.More(); iter.Next())
- if(iter.Current() == iterToRemove)
- iter.RemoveCurrent();
- }
-
- //-------------------------------------------------------------------
- // TListStorage::InsureSpaceForIteratorList
- //-------------------------------------------------------------------
- void TListStorage::InsureSpaceForIteratorList(UInt16 numberOfItersNeeded)
- {
- if(numberOfItersNeeded > fIteratorListReservedSpace)
- {
- UInt16 newReserveSpace = fIteratorListReservedSpace + kIterListAllocationChunk;
-
- TAbstractListIterator** newIterList = new TAbstractListIterator*[newReserveSpace];
- if(fIteratorListReservedSpace > 0)
- BlockMoveData(fIteratorList, newIterList, fIteratorListReservedSpace * sizeof(Ptr));
- delete fIteratorList;
- fIteratorList = newIterList;
-
- fIteratorListReservedSpace = newReserveSpace;
- }
- }
-
- //-------------------------------------------------------------------
- // TListStorage::NotifyItemAdded
- //-------------------------------------------------------------------
- void TListStorage::NotifyItemAdded(SInt32 indexOfNewItem)
- {
- for(TAbstractListIteratorIterator iter(fIteratorList, &fNumberOfIterators); iter.More(); iter.Next())
- iter.Current()->NotifyItemAdded(indexOfNewItem);
- }
-
- //-------------------------------------------------------------------
- // TListStorage::NotifyItemRemoved
- //-------------------------------------------------------------------
- void TListStorage::NotifyItemRemoved(SInt32 indexOfItemRemoved)
- {
- for(TAbstractListIteratorIterator iter(fIteratorList, &fNumberOfIterators); iter.More(); iter.Next())
- iter.Current()->NotifyItemRemoved(indexOfItemRemoved);
- }
-
- //-------------------------------------------------------------------
- // TListStorage::NotifyListDestroyed
- //-------------------------------------------------------------------
- void TListStorage::NotifyListDestroyed()
- {
- for(TAbstractListIteratorIterator iter(fIteratorList, &fNumberOfIterators); iter.More(); iter.Next())
- iter.Current()->NotifyListDestroyed();
- }
-
-